package com.evosoft.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.persistence.*;
import javax.persistence.criteria.CriteriaQuery;

import com.evosoft.excepciones.NotEntityFoundException;


abstract class GenericDao<E> implements Serializable {
	private static final long serialVersionUID = 1L;
        public static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("bienestarPU");
	private EntityManager em = emf.createEntityManager();

	private Class<E> entityClass;

	
	public GenericDao(Class<E> entityClass) {
		this.entityClass = entityClass;
	}

	public void create(E entity, EntityManager em){
        em.persist(entity);
    }
    
    public void update(E entity, EntityManager em){
        em.merge(entity);
    }
    
    public void delete(E entity, EntityManager em) throws NotEntityFoundException{
        if(entity == null){
            throw new NotEntityFoundException();
        }
        em.remove(entity);
    }
    
    public E findById(Object id, EntityManager em) throws NotEntityFoundException{
       E entidad = em.find(entityClass, id);
       if(entidad == null){
           throw new NotEntityFoundException();
       }
       return entidad;
    }
    
    public List<E> findAll(EntityManager em){
        CriteriaQuery criteriaQuery = em.getCriteriaBuilder().createQuery();
        criteriaQuery.select(criteriaQuery.from(entityClass));
        return em.createQuery(criteriaQuery).getResultList();
    }

	// Using the unchecked because JPA does not have a
	// query.getSingleResult()<T> method
	@SuppressWarnings("unchecked")
	protected E findOneResult(String namedQuery, Map<String, Object> parameters) {
		E result = null;

		try {
			Query query = em.createNamedQuery(namedQuery);

			// Method that will populate parameters if they are passed not null and empty
			if (parameters != null && !parameters.isEmpty()) {
				populateQueryParameters(query, parameters);
			}

			result = (E) query.getSingleResult();

		} catch (NoResultException e) {
			System.out.println("No result found for named query: " + namedQuery);
		} catch (Exception e) {
			System.out.println("Error while running query: " + e.getMessage());
			e.printStackTrace();
		}

		return result;
	}

	private void populateQueryParameters(Query query, Map<String, Object> parameters) {
		for (Entry<String, Object> entry : parameters.entrySet()) {
			query.setParameter(entry.getKey(), entry.getValue());
		}
	}
}